package com.atguigu.gmall.search.listener;

import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.pms.entity.*;
import com.atguigu.gmall.search.feign.GmallPmsClient;
import com.atguigu.gmall.search.feign.GmallWmsClient;
import com.atguigu.gmall.search.pojo.Goods;
import com.atguigu.gmall.search.pojo.SearchAttrValueVo;
import com.atguigu.gmall.search.repository.GoodsRepository;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Jia Fa
 * @create 2021-12-09 14:48
 */
@Component
@Slf4j
public class SpuInfoListener {

    @Autowired
    private GmallPmsClient pmsClient;
    @Autowired
    private GmallWmsClient wmsClient;
    @Autowired
    private GoodsRepository repository;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "PMS_SPU_SAVE_QUEUE", durable = "true"),
            exchange = @Exchange(value = "PMS_ITEM_EXCHANGE", ignoreDeclarationExceptions = "true", type = ExchangeTypes.TOPIC),
            key = {"pms.spuSave"}
    ))
    public void listenCreate(Long SpuId, Channel channel, Message message) throws IOException {
        try {
            // 根据消息队列的SpuId 查询最新的spu数据设置到 es中

            // 下方需要根据spuEntity查询到分类Id,品牌Id,创建时间
            ResponseVo<SpuEntity> spuEntityResponseVo = this.pmsClient.querySpuById(SpuId);
            SpuEntity spuEntity = spuEntityResponseVo.getData();

            //根据spuId查询Sku的集合
            ResponseVo<List<SkuEntity>> SkuPage = this.pmsClient.querySkuBySpuId(SpuId);
            List<SkuEntity> skuEntities = SkuPage.getData();

            if (!CollectionUtils.isEmpty(skuEntities)) {

                //4 品牌信息查询 设置  根据brandId  放在这里根据spu类获得Cid 可以减少查询次数，放在下面根据SKu查询cid查询次数暴涨，注意查询品牌需要Sku存在，所以在sku集合判空后再进行查询
                ResponseVo<BrandEntity> brandVo = this.pmsClient.queryBrandById(spuEntity.getBrandId());
                BrandEntity brandEntity = brandVo.getData();

                //5 分类信息查询 同上
                ResponseVo<CategoryEntity> categoryResponseVo = this.pmsClient.queryCategoryById(spuEntity.getCategoryId());
                CategoryEntity categoryEntity = categoryResponseVo.getData();

                // 7 检索类型的普通属性 原因同上
                ResponseVo<List<SpuAttrValueEntity>> SpuResponseVo = this.pmsClient.querySearchSpuAttrValueByCidAndSpuId(spuEntity.getCategoryId(), SpuId);
                List<SpuAttrValueEntity> spuAttrValueEntities = SpuResponseVo.getData();

                //遍历每一个SKu 把sku集合转化成goods集合
                List<Goods> goodsList = skuEntities.stream().map(skuEntity -> {
                    Goods goods = new Goods();
                    //设置sku信息
                    goods.setSkuId(skuEntity.getId());
                    goods.setTitle(skuEntity.getTitle());
                    goods.setDefaultImage(skuEntity.getDefaultImage());
                    goods.setPrice(skuEntity.getPrice());
                    goods.setSubtitle(skuEntity.getSubtitle());

                    //设置spu信息
                    goods.setCreateTime(spuEntity.getCreateTime());
                    // 3 根据SkuId 查询库存信息
                    ResponseVo<List<WareSkuEntity>> WmsPage = this.wmsClient.queryWareSkuBySid(skuEntity.getId());
                    List<WareSkuEntity> wareSkuEntities = WmsPage.getData();

                    //库存信息设置
                    if (!CollectionUtils.isEmpty(wareSkuEntities)) {
                        //sales store
                        goods.setSales(wareSkuEntities.stream().map(WareSkuEntity::getSales).reduce((a, b) -> a + b).get()); //流的归约应用 查询同一个Sku的所有销量
                        goods.setStore(wareSkuEntities.stream().anyMatch(w -> w.getStock() - w.getStockLocked() > 0)); //anyMatch 存在任意一个stock则返回TRUE
                    }
                    //4 设置品牌信息
                    if (brandEntity != null) {
                        goods.setBrandId(brandEntity.getId());
                        goods.setBrandName(brandEntity.getName());
                        goods.setLogo(brandEntity.getLogo());
                    }
                    //5 分类信息设置 判空
                    if (categoryEntity != null) {
                        goods.setCategoryId(categoryEntity.getId());
                        goods.setCategoryName(categoryEntity.getName());
                    }
                    //存储检索类型字段的集合
                    ArrayList<SearchAttrValueVo> searchAttrValueVos = new ArrayList<>();
                    //检索类型的销售属性  search_type =1  根据cid 和 skuId
                    ResponseVo<List<SkuAttrValueEntity>> skuResponseVo = this.pmsClient.querySearchSkuAttrValueByCidAndSkuId(skuEntity.getCategoryId(), skuEntity.getId());
                    List<SkuAttrValueEntity> skuAttrValueEntities = skuResponseVo.getData();
                    if (!CollectionUtils.isEmpty(skuAttrValueEntities)) {
                        searchAttrValueVos.addAll(
                                skuAttrValueEntities.stream().map(skuAttrValueEntity -> {
                                            SearchAttrValueVo searchAttrValueVo = new SearchAttrValueVo();

                                            BeanUtils.copyProperties(skuAttrValueEntity, searchAttrValueVo);
                                    /*searchAttrValueVo.setAttrId(skuAttrValueEntity.getId());
                                    searchAttrValueVo.setAttrName(skuAttrValueEntity.getAttrName());
                                    searchAttrValueVo.setAttrValue(skuAttrValueEntity.getAttrValue());*/

                                            return searchAttrValueVo;
                                        }
                                ).collect(Collectors.toList()));
                    }

                    // 设置检索类型的普通属性

                    if (!CollectionUtils.isEmpty(spuAttrValueEntities)) {
                        searchAttrValueVos.addAll(spuAttrValueEntities.stream().map(spuAttrValueEntity -> {

                            SearchAttrValueVo searchAttrValueVo = new SearchAttrValueVo();

                            BeanUtils.copyProperties(spuAttrValueEntity, searchAttrValueVo);

                            return searchAttrValueVo;
                        }).collect(Collectors.toList()));
                    }
                    // 设置检索参数属性
                    goods.setAttrList(searchAttrValueVos);
                    return goods;
                }).collect(Collectors.toList());

                this.repository.saveAll(goodsList);

            }
            // 手动确认   投递的游标  不确认后面的队列信息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            e.printStackTrace();
            // * channel.basicAck  手动确认
            // * channel.basicNack  重试入列
            // * channel.basicReject 直接拒绝
            // 如果已经执行过重试策略则直接拒绝掉
            if (message.getMessageProperties().getRedelivered()) {
                // 拒绝策略 requeue 是否重新入队列
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);

            }else {
                // 重新入列
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
            }
        }
    }
}